package fun.hijklmn.magic.admin.server.filter;

import fun.hijklmn.magic.admin.server.properties.JwtProperties;
import fun.hijklmn.magic.admin.server.handler.JwtHandler;
import fun.hijklmn.magic.common.constants.CharsetConstant;
import fun.hijklmn.magic.common.constants.ContentTypeConstant;
import fun.hijklmn.magic.common.enums.ResponseCodeEnum;
import fun.hijklmn.magic.common.utils.JsonUtil;
import fun.hijklmn.magic.common.utils.ResultVOUtil;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.web.AuthenticationEntryPoint;
import org.springframework.security.web.authentication.www.BasicAuthenticationFilter;

import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.Collections;

/**
 * @Description
 * @Author fs
 * @Date 2021/6/26 11:57
 * @Version 0.0.1-SNAPSHOT
 **/
public class JWTAuthorizationFilter extends BasicAuthenticationFilter {

    private JwtHandler jwtHandler;

    private JwtProperties jwtProperties;

    @Override
    protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain chain) throws IOException, ServletException {

        String tokenHeader = request.getHeader(jwtProperties.getTokenHeader());

        if (tokenHeader == null || !tokenHeader.startsWith(jwtProperties.getTokenPrefix())) {
            chain.doFilter(request, response);
            return;
        }

        String token = tokenHeader.replace(jwtProperties.getTokenHeader(), "");

        boolean expiration = jwtHandler.isExpire(token);

        if (!expiration) {
            String username = jwtHandler.getUsername(token);
            String role = jwtHandler.getRole(token);
            if (username != null){
                SecurityContextHolder.getContext().setAuthentication(new UsernamePasswordAuthenticationToken(username, null, Collections.singleton(new SimpleGrantedAuthority(role))));
            }
        } else {
            response.setCharacterEncoding(CharsetConstant.UTF8);
            response.setContentType(ContentTypeConstant.APPLICATION_JSON);
            response.setStatus(HttpServletResponse.SC_FORBIDDEN);
            response.getWriter().write(JsonUtil.toJsonString(ResultVOUtil.parse(ResponseCodeEnum.SESSION_EXPIRED)));
            response.getWriter().flush();
            return;
        }

        super.doFilterInternal(request, response, chain);

    }

    public void setJwtHandler(JwtHandler jwtHandler) {
        this.jwtHandler = jwtHandler;
    }

    public void setJwtProperties(JwtProperties jwtProperties) {
        this.jwtProperties = jwtProperties;
    }

    public JWTAuthorizationFilter(AuthenticationManager authenticationManager, JwtProperties jwtProperties, JwtHandler jwtHandler) {
        super(authenticationManager);
        this.jwtProperties = jwtProperties;
        this.jwtHandler = jwtHandler;
    }

    public JWTAuthorizationFilter(AuthenticationManager authenticationManager) {
        super(authenticationManager);
    }

    public JWTAuthorizationFilter(AuthenticationManager authenticationManager, AuthenticationEntryPoint authenticationEntryPoint) {
        super(authenticationManager, authenticationEntryPoint);
    }

}
